package net.chemistry;

import java.io.Serializable;

import net.ChemistryException;
import net.util.ChemistryUtil;
import net.util.SumCalc;
import net.util.ArrayList2;

public class ElectronCloud implements Serializable
{

	private static final long serialVersionUID = 8591881308038269301L;
	
	private ArrayList2<ElectronShell> shells = new ArrayList2<>();
	
	public ElectronCloud(final int e)
	{		
		int topLevel = ChemistryUtil.getLevel(e);
		
		for (int i = 0; i < topLevel - 1; i++)
		{
			shells.add(new ElectronShell(i));
		}
		
		int rem = e - ChemistryUtil.nobleConfig(topLevel-1);
		
		//System.out.println(rem);
		
		shells.add(new ElectronShell(topLevel, rem));
	}
	
	public String toString()
	{
		String str = "";
		
		ElectronShell eShell = shells.peekL();
		
		if (eShell.isNoble())
		{
			str += "[" + AtomID.Nobles[shells.size()-1].abbrev + "]"; 
		}
		else
		{
			if (shells.size() > 1)
			{
				str = "[" + AtomID.Nobles[shells.size()-2].abbrev + "]";
			}
			
			str += shells.peekL().toString();
		}
		
		return str;
	}
	
	public int toNextNoble()
	{
		ElectronShell eshell = shells.peekL();
		
		return ChemistryUtil.nobleConfig(eshell.getLevel()) - eshell.geteInLevel();
	}
	
	public int getCharge()
	{
		return (int) shells.sum(new SumCalc<ElectronShell>()
					 {
					 	public double evaluate(ElectronShell e)
					 	{
					 		return e.geteInLevel();
					 	}
					 });
	}

	public int getLevel()
	{
		return shells.size();
	}
	
	public void oxidize() throws ChemistryException
	{
		if (shells.isEmpty())
		{
			shells.add(new ElectronShell(1,1));
		}
		else if (shells.peekL().isFull())
		{
			throw new ChemistryException("Cannot oxidize atom in Nobel configuration.");
		}
		else
		{
			shells.peekL().oxidize();
		}
	}
	
	public void reduce() throws ChemistryException
	{
		if (shells.isEmpty())
		{
			throw new ChemistryException("Cloud does not contain any electron shells.");
		}
		
		ElectronShell eShell = shells.peekL();
		
		if (eShell.isFull())
		{
			shells.add(new ElectronShell(eShell.getLevel() + 1,1));
		}
		else
		{
			eShell.reduce();
		}
	}

	public void render(int x, int y, float angle)
	{
		for(ElectronShell eShell : shells)
		{
			eShell.render(x, y, angle);
		}
	}

	public void share(int bonds) throws ChemistryException
	{
		if (shells.isEmpty())
		{
			throw new ChemistryException("No electrons to share.");
		}
		
		for(int n = 0; n < bonds; n++)
		{
			shells.peekL().share();
		}
	}
}
